package topics

import (
	"context"
	"github.com/go-kit/kit/endpoint"
)

// createKeywordTopicRequest是创建关键字专题接口的请求体
type createKeywordTopicRequest struct {
	// 专题名称
	Name           string     `json:"name"`
	// 是否启用
	Enabled        bool       `json:"enabled"`
	// 有效时间的开始时间戳，以ms为单位
	BeginTimestamp *int64     `json:"beginTimestamp"`
	// 有效时间的停用时间戳，以ms为单位
	EndTimestamp   *int64     `json:"endTimestamp"`
	// 关键字对象的列表 内含: op(enum):exclude、include  keywords: 关键字字符串以空格分割
	Keywords       []Keywords `json:"keywords"`
	// 备注
	Comment        *string    `json:"comment"`
	// 父专题的id
	ParentId       *string    `json:"parentId"`
}

// createTopicResponse是创建关键字专题接口的响应体
type createTopicResponse struct {
	// 创建成功响应Topic数据，复用Topic
	Topic
	// 创建失败仅响应Error
	Error string `json:"error,omitempty"`
}

// updateKeywordTopicRequest时修改单个关键字专题接口的请求体
type updateKeywordTopicRequest struct {
	// 专题id
	Id              string     `json:"id"`
	// 专题名称
	Name            string     `json:"name"`
	// 是否启用
	Enabled         bool       `json:"enabled"`
	// 关键字类型列表
	Keywords        []Keywords `json:"keywords"`
	// 备注
	Comment         *string    `json:"comment"`
	// 创建时的时间戳，以ms为单位
	CreateTimestamp int64      `json:"createTimestamp"`
	// 有效时间的开始时间戳
	BeginTimeStamp  *int64     `json:"beginTimestamp"`
	// 有效时间的停用时间戳
	EndTimestamp    *int64     `json:"endTimestamp"`
}

// updateKeywordTopicResponse时更新单个关键字专题的响应体
type updateKeywordTopicResponse struct {
	// 复用Topic结构体，Topic中的字段与Error同级，在正常时响应
	Topic
	// 异常时仅响应Error
	Error string `json:"error,omitempty"`
}

// switchEnabledKeywordTopicRequest是单个关键字专题启用开关的请求体
type switchEnabledKeywordTopicRequest struct {
	// 专题id
	Id      string
	// 是否启用
	Enabled bool
}

// deleteKeywordTopicRequest是单个关键字专题删除的请求体
type deleteKeywordTopicRequest struct {
	// 专题id
	Id    string `json:"id,omitempty"`
	// 异常时仅响应Error
	Error string `json:"error,omitempty"`
}

// delOrSwitchEnabledKeywordTopicResponse是单个关键字专题启用开关或者删除公用的响应体
type delOrSwitchEnabledKeywordTopicResponse struct {
	// 处理正常返回专题id
	Id    string `json:"id,omitempty"`
	// 异常时仅响应Error
	Error string `json:"error,omitempty"`
}

// getKeywordTopicsRequest为获取分页关键字专题的请求体
type getKeywordTopicsRequest struct {
	// Page为第几页的页码，从1开始
	Page int `json:"page"`
	// Size为单个页面的关键字专题个数
	Size int `json:"size"`
}

// getKeywordTopicsResponse是获取分页关键字专题接口的响应体
type getKeywordTopicsResponse struct {
	// 单个页面中关键字专题的列表
	Data  []Topic `json:"data"`
	// 全量一级关键字专题的总数，用于前端分页
	Total int     `json:"total"`
	// 业务逻辑出错时只响应Error
	Error string  `json:"error,omitempty"`
}

// getSmartTopicsRequest为获取分页智能专题的请求体
type getSmartTopicsRequest struct {
	// Page为第几页的页码，从1开始
	Page int `json:"page"`
	// Size为单个页面的智能专题个数
	Size int `json:"size"`
}

// getSmartTopicsResponse为获取分页智能专题的响应体
type getSmartTopicsResponse struct {
	// 单个页面中智能专题数据列表
	Data  []SmartTopic `json:"data"`
	// 全量智能专题的个数，用于前端分页
	Total int          `json:"total"`
	// 异常时仅响应Error
	Error string       `json:"error,omitempty"`
}

// makeCreateKeywordTopicEndpoint是创建关键字专题接口的endpoint
// 1，获取到请求体
// 2，调用服务层代码进行处理
// 3，序列化结果为响应体返回
func makeCreateKeywordTopicEndpoint(svc Service) endpoint.Endpoint {
	return func(ctx context.Context, request interface{}) (response interface{}, err error) {
		req := request.(createKeywordTopicRequest)
		// 将请求题序列化为领域模型调用相关服务
		topic := &Topic{
			Name:           req.Name,
			Enabled:        req.Enabled,
			BeginTimestamp: req.BeginTimestamp,
			EndTimestamp:   req.EndTimestamp,
			Comment:        req.Comment,
			Keywords:       req.Keywords,
			ParentId:       req.ParentId,
		}
		// 调用服务的CreateTopic方法创建专题，并对异常进行处理
		topic, err = svc.CreateTopic(ctx, topic)
		if err != nil {
			return createTopicResponse{Error: err.Error()}, nil
		}
		return createTopicResponse{Topic: *topic}, nil
	}
}

// makeGetKeywordTopicsEndpoint是获取分页关键字专题的endpoint
// 1.获取到请求体
// 2.调用领域层服务获取全量关键字专题
// 3.将关键字专题分层(暂时分为两层)
// 4.对分页进行处理，访问超出数量的专题返回空数据但不报错
// 5.序列化为响应体
func makeGetKeywordTopicsEndpoint(svc Service) endpoint.Endpoint {
	return func(ctx context.Context, request interface{}) (response interface{}, err error) {
		req := request.(getKeywordTopicsRequest)
		topics, total, err := svc.GetTopics(ctx, req.Page, req.Size)
		if err != nil {
			return getKeywordTopicsResponse{Error: err.Error()}, nil
		}
		if len(topics) == 0{
			return getKeywordTopicsResponse{}, nil
		}
		return getKeywordTopicsResponse{
			Data:  topics,
			// 这里返回全量一级父关键字专题的总个数，用于前端进行分页展示
			Total: total,
		}, nil
	}
}

// makeGetSmartTopicsEndpoint是获取分页智能专题的endpoint
// 1.获取请求体
// 2.对分页数量范围进行判断，超出数量范围返回空数据但不报错
// 3.调用服务层获取分页范围内的智能专题列表
// 4.序列化响应体返回
// tip:智能专题不需要分层，默认为1层
func makeGetSmartTopicsEndpoint(svc SmartTopicsService) endpoint.Endpoint {
	return func(ctx context.Context, request interface{}) (response interface{}, err error) {
		req := request.(getSmartTopicsRequest)
		if (req.Page-1)*req.Size >= svc.Length(ctx) {
			return getSmartTopicsResponse{}, nil
		}
		// 获取氛围范围内的智能专题列表
		var res []SmartTopic
		if req.Page*req.Size >= svc.Length(ctx) {
			res = svc.Get(ctx)[(req.Page-1)*req.Size:]
		} else {
			res = svc.Get(ctx)[(req.Page-1)*req.Size : req.Page*req.Size]
		}
		return getSmartTopicsResponse{
			Data:  res,
			// 这里返回全量智能专题的总数
			Total: svc.Length(ctx),
		}, nil
	}
}

// makeUpdateKeywordTopicEndpoint是更新单个关键字专题的endpoint
// 1.获取请求体
// 2.调用领域服务获取单个专题，并对异常进行处理
// 3.将可进行修改的字段进行赋值
// 4.调用领域服务进行更新，并对错误进行处理
// 5.序列化响应体返回
func makeUpdateKeywordTopicEndpoint(svc Service) endpoint.Endpoint {
	return func(ctx context.Context, request interface{}) (response interface{}, err error) {
		req := request.(updateKeywordTopicRequest)
		// 先获取专题判断专题是否存在
		topic, err := svc.GetTopic(ctx, req.Id)
		if err != nil {
			return updateKeywordTopicResponse{Error: err.Error()}, nil
		}
		// 对可进行修改的字段进行赋值
		topic.Name = req.Name
		topic.Enabled = req.Enabled
		topic.Keywords = req.Keywords
		topic.Keywords = req.Keywords
		topic.Comment = req.Comment
		topic.BeginTimestamp = req.BeginTimeStamp
		topic.EndTimestamp = req.EndTimestamp
		// 更新关键字专题
		topic, err = svc.UpdateTopic(ctx, topic)
		if err != nil {
			return updateKeywordTopicResponse{Error: err.Error()}, nil
		}
		return updateKeywordTopicResponse{Topic: *topic}, nil
	}
}

// makeDeleteKeywordTopicEndpoint是单个关键字专题删除接口的endpoint；启用开关与专题删除共用
// 1.判断是启用开关还是专题删除
// 2.调用相关的领域服务进行处理
// 3.序列化响应体返回
func makeDeleteKeywordTopicEndpoint(svc Service) endpoint.Endpoint {
	return func(ctx context.Context, request interface{}) (response interface{}, err error) {
		switch req := request.(type) {
		// 对请求体进行判断并调用相关的服务进行处理
		case switchEnabledKeywordTopicRequest:
			topic, err := svc.GetTopic(ctx, req.Id)
			if err != nil {
				return delOrSwitchEnabledKeywordTopicResponse{Error: err.Error()}, err
			}
			topic.Enabled = req.Enabled
			topic, err = svc.UpdateTopic(ctx, topic)
			if err != nil {
				return delOrSwitchEnabledKeywordTopicResponse{Error: err.Error()}, err
			}
			return delOrSwitchEnabledKeywordTopicResponse{Id: topic.Id}, nil
		case deleteKeywordTopicRequest:
			topic, err := svc.GetTopic(ctx, req.Id)
			if err != nil {
				return delOrSwitchEnabledKeywordTopicResponse{Error: err.Error()}, nil
			}
			err = svc.DeleteTopic(ctx, topic.Id)
			if err != nil {
				return delOrSwitchEnabledKeywordTopicResponse{Error: err.Error()}, err
			}
			return delOrSwitchEnabledKeywordTopicResponse{Id: topic.Id}, nil
		default:
			// 若非启用开关或删除请求进行异常响应
			return delOrSwitchEnabledKeywordTopicResponse{Error: "请求参数错误"}, err
		}
	}
}
